home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / cross / caz.lha / caz / caz.c < prev    next >
C/C++ Source or Header  |  1993-11-25  |  61KB  |  2,507 lines

  1. #include "defs.h"
  2. #include "cazerrors.h"
  3.  
  4. /*#define DEBUG2 */    /* internal use for more debugging (print out coded MNE) */
  5. /*#define DEBUG_STRTOINT*/  /* debug strtoint() funktion */
  6.  
  7.  
  8. #define MODE_ALL    1        /* Verbose Mode: Print out all source text */
  9. #define MODE_MNE    2        /* Verbose Mode: Print out only MNE text */
  10. #define MODE_OPTION 4        /* if Verbose Mode is set via Commandline Option */
  11.  
  12. #define ACT_OBJ_ADDR(pobj) (((u_char *)(pobj->objbuffer+(pobj->actbyte-pobj->firstbyte))))
  13.  
  14. #define COPYRIGHT "©1992/93 by Carsten Rose\n"
  15. const char *vers = "\0$VER: Z80_Assenbler 1.25ß (24 November,93)";
  16.  
  17. extern char *directives[];        /* declared in File 'cazmne.c' */
  18. extern struct command cmd[];    /* declared in File 'cazmne.c' */
  19.  
  20. static int        init                (struct listheader *plabel,struct objsize *pobj);
  21. static void    symboltable        (struct listheader *plabel);
  22. static int     writesymboltable    (struct listheader *plabel,char *filename);
  23. static char   *ibtoh            (u_char byte,char *pbuf);
  24. static char   *iwtoh            (unsigned short word,char *pbuf);
  25. static void    decodearg        (char *str,u_long pa);
  26. static void    cutend            (char *pos);
  27. static char   *skipspace        (char *pos);
  28. static void    killcomment        (char *pos);
  29. static int        expandlist        (struct listheader *plist);
  30. static struct labelitem 
  31.               *insertlabel        (struct listheader *plabel,char *name,int type,u_short value,BOOL valid);
  32. static int        dolabel            (struct listheader *plabel,struct objsize *pobjcode,char   *lname);
  33. static int        finddirective    (char *pos);
  34. static struct command
  35.               *findmne            (struct command *pcmd,char *pmne);
  36. static u_long  argtype            (struct listheader *plabel,char *pos,u_short *pshort,int mode);
  37. static int        doobjadr            (struct objsize *pobj,int n,int mode);
  38. static u_char  codebits            (u_long mask);
  39. static int        writemnedata        (struct objsize *pobj,u_long maskarg,u_short val,u_long maskcmd,u_char pos);
  40. static int        fillihbuffer        (int addr,int nbytes,u_char *pbuf);
  41. static int        dointelhex        (int addr,int size,u_char *data);
  42. static int        makecode            (struct objsize *pobj,struct command *pcmd,int mode,u_long type1,u_short val1,u_long type2,u_short val2);
  43. static int        domne            (struct listheader *plabel,struct objsize *pobj,char *ptok,int mode,u_short *pcycle);
  44. static int       pushfile            (struct item_file **pstack,char *p_filenamenew,FILE **p_fp);
  45. static int       popfile            (struct item_file **pstack,FILE **p_fp);
  46. static int        dodirective        (struct listheader *plabel,struct objsize *pobj,char *ptok,int direc,int mode,int *orgflag);
  47. static int        parseline        (struct listheader *plabel,struct objsize *pobj,char *pwork,int mode);
  48. static int        readsrc            (struct listheader *plabel,struct objsize *pobj,char *p_actname);
  49.  
  50. int            main             (int argc,char *argv[]);
  51.             
  52. int     lnr=0,errors=0,
  53.         debugv=FALSE,            /* debug values, set via Commandline option */ 
  54.         debugf=FALSE,            /* debug functions, set via Commandline option */ 
  55.         verbose=FALSE,            /* set via Commandline option */
  56.         intelhex=FALSE,            /* set via Commandline option */
  57.         clockcycle=FALSE,            /* set via Commandline option */
  58.         showsymbols=FALSE;        /* set via Commandline option */
  59. char    errortext[BUFSIZ],        /* Common Buffer for Error Messages */
  60.         line[BUFSIZ],            /* Actual read Source text line (original) */
  61.         work[BUFSIZ],            /* Actual read Source text line (truncated,modified) */
  62.         actfilename[FILENAME_MAX]; /* Actual Filename of assembled Source File */
  63.  
  64. struct    listheader  ih_head;
  65. struct    listheader label;
  66. struct    objsize    object;
  67. struct  item_file    *file_stack=NULL;
  68.  
  69. BOOL    endflag=FALSE,            /* Set if END is found */
  70.         assembleflag=TRUE;        /* Normal TRUE, only if 'COND xx' xx==0 then FALSE */
  71. FILE     *fpin=NULL,*fpout=NULL;
  72.  
  73.  
  74. static void showerror(char *errpos, char *fmt , ...)
  75. {
  76.     /*
  77.      * Print parsing error:
  78.      *
  79.      *   xxxx:........................
  80.      *              ^
  81.      *   'Error Description'
  82.      */
  83.  
  84.         int i;
  85.         va_list pa;
  86.         char buffer[BUFSIZ];
  87.  
  88.     if(debugf)  puts("showerror");
  89.  
  90.         /* If there are more than 1 source files - print Filenames */
  91.     if(file_stack)
  92.         fprintf(stderr,"Error in File:%s\n",actfilename);
  93.  
  94.     fprintf(stderr,"%4d:%s",lnr,line);        /* line number and Source code line */
  95.  
  96.     i = strlen(line);
  97.  
  98.     if(!i)                /* not really needed */
  99.         return;
  100.  
  101.     if(line[i-1]!='\n')
  102.         fputs("\n",stderr);
  103.  
  104.     if(!errpos)
  105.         errpos=work;
  106.  
  107.     i = (int)(errpos - work);
  108.  
  109.     buffer[i]='\0';
  110.  
  111.     while(i--)
  112.     {
  113.         if(line[i]=='\t')
  114.             buffer[i]='\t';
  115.         else
  116.             buffer[i]=' ';
  117.     }
  118.  
  119.     fprintf(stderr,"     %s^ ",buffer);        /* mark position */
  120.  
  121.     va_start(pa,fmt);
  122.     vfprintf(stderr,fmt,pa);                /* Print Errormessage */
  123.     va_end(pa);
  124.     fputs("\n",stderr);
  125.     errors++;                        /* count errors */
  126. }
  127.  
  128. static int init(struct listheader *plabel,struct objsize *pobj)
  129. {
  130.     /*
  131.      * Init listheader
  132.      *
  133.      * RC : NULL if all went fine 
  134.      */
  135.      
  136.  
  137.     if(debugf)  puts("init");
  138.  
  139.     plabel->nitem = 0;
  140.     plabel->actitem = 0;
  141.     plabel->sizeitem = sizeof(struct labelitem);
  142.     plabel->newnitem = NEWITEMOFF;
  143.     plabel->userdata = ERROR;
  144.     plabel->list = NULL;
  145.  
  146.     ih_head.nitem = 0;
  147.     ih_head.actitem = 0;
  148.     ih_head.sizeitem = sizeof(u_char);
  149.     ih_head.newnitem = 4096;
  150.     ih_head.userdata = ERROR;
  151.     ih_head.list = NULL;
  152.  
  153.     pobj->firstbyte = ERROR;
  154.     pobj->actbyte   = ERROR;
  155.     pobj->lastbyte  = ERROR;
  156.     pobj->objbuffer = NULL;
  157.  
  158.     return(NULL);
  159. }
  160.  
  161. static void symboltable(struct listheader *plabel)
  162. {
  163.     int i;
  164.     struct labelitem *lst;
  165.     char *pltyp;
  166.  
  167.     if(debugf)  puts("symboltable");
  168.  
  169.     lst = plabel->list;
  170.     i   = plabel->actitem;
  171.     puts("Lable's:");
  172.  
  173.     while(i--)
  174.     {
  175.         switch(lst->type)
  176.         {
  177.             case L_EQU:        pltyp = "EQU";
  178.                             break;
  179.             case L_DEFL:    pltyp = "DEFL";
  180.                             break;
  181.             case L_POSITION:
  182.                             pltyp = "POSITION";
  183.                             break;
  184.             deafult:        pltyp = "unknown";
  185.                             INTERNAL_ERROR
  186.                             break;
  187.         }
  188.         
  189.         printf("Name:%-32s  Type:%-8s  Value:0x%X\n",lst->name,pltyp,lst->value);
  190.         lst++;
  191.     }
  192. }
  193.  
  194. static int writesymboltable(struct listheader *plabel,char *filename)
  195. {
  196.     /* Write all Labels as EQU definition's with associated values into
  197.      * 'filename'
  198.      *
  199.      * RC: NULL if all went fine else
  200.      *     ERROR
  201.      */
  202.  
  203.     int i;
  204.     struct labelitem *lst;
  205.     FILE   *fplabel;
  206.  
  207.     if(debugf)  puts("writesymboltable");
  208.  
  209.     lst = plabel->list;
  210.     i   = plabel->actitem;
  211.  
  212.     if(!(fplabel = fopen(filename,"wb")))    /* open file where to write Label's */
  213.     {
  214.         perror("Can't open file:");
  215.         return(ERROR);
  216.     }
  217.  
  218.     while(i--)
  219.     {
  220.         if(fprintf(fplabel,"%-32s EQU 0x%X\n",lst->name,lst->value)<0)
  221.         {
  222.             perror("Writing Labelfile failed");
  223.             fclose(fplabel);
  224.             return(ERROR);
  225.         }
  226.         lst++;
  227.     }
  228.  
  229.     fclose(fplabel);
  230.  
  231.     return(NULL);
  232. }
  233.  
  234.  
  235. static char *ibtoh(unsigned char byte,char *pbuf)
  236. {
  237.     /* Convert 'byte' in ASCII Hex Notation.
  238.      * 
  239.      * Write ASCII Hex Code (2 Chars) at '*pbuf'.
  240.      *
  241.      * RC: pbuf+2    (points to next free char)
  242.      */  
  243.  
  244.     unsigned char     low,    /* low 4 Bits of 'byte' */
  245.             high;    /* high 4 Bits of 'byte' (normalized) */
  246.  
  247.     low = 0x0F&byte;
  248.     high = (0xF0&byte)>>4;
  249.  
  250.     /* convert Integer to ASCII Hex */
  251.     *pbuf++= (high<=9) ? high+'0' : (high-0x0A)+'A';
  252.     *pbuf++= (low<=9) ? low+'0' : (low-0x0A)+'A';
  253.  
  254.     return(pbuf);
  255. }
  256.  
  257. static char *iwtoh(u_short word,char *pbuf)
  258. {
  259.     /* Convert 'word' in ASCII Hex Notation.
  260.      * 
  261.      * Write ASCII Hex Code (4 Chars) at '*pbuf'.
  262.      *
  263.      * RC: pbuf+4    (points to next free char)
  264.      */  
  265.  
  266.     char *pos;
  267.     u_char lowb,highb;
  268.  
  269.     lowb = (u_char)(word & 0xFF);
  270.     highb = (u_char)(word >> 8);
  271.  
  272.     pos=ibtoh(highb,pbuf);
  273.     pos=ibtoh(lowb,pos);
  274.  
  275.     return(pos);
  276. }
  277.  
  278. static void decodearg(char *str,u_long pa)
  279. {
  280.     char pos[256];
  281.  
  282.     if(debugf)  puts("decodearg");
  283.  
  284.     pos[0]='\0';
  285.  
  286.     if( (pa^BRA)&BRA)
  287.     {
  288.         if(!( (pa®8)^REG8))
  289.             strcat(pos,"REG8   ");
  290.         else if(!( (pa®16)^REG16))
  291.             strcat(pos,"REG16  ");
  292.         else
  293.         {
  294.             if(pa®_A)  strcat(pos,"REG_A  ");
  295.             if(pa®_B)  strcat(pos,"REG_B  ");
  296.             if(pa®_C)  strcat(pos,"REG_C  ");
  297.             if(pa®_D)  strcat(pos,"REG_D  ");
  298.             if(pa®_F)  strcat(pos,"REG_F  ");
  299.             if(pa®_H)  strcat(pos,"REG_H  ");
  300.             if(pa®_I)  strcat(pos,"REG_I  ");
  301.             if(pa®_L)  strcat(pos,"REG_L  ");
  302.             if(pa®_R)  strcat(pos,"REG_R  ");
  303.             if(pa®_AF) strcat(pos,"REG_AF ");
  304.             if(pa®_BC) strcat(pos,"REG_BC ");
  305.             if(pa®_DE) strcat(pos,"REG_DE ");
  306.             if(pa®_HL) strcat(pos,"REG_HL ");
  307.             if(pa®_SP) strcat(pos,"REG_SP ");
  308.             if(pa®_IX) strcat(pos,"REG_IX ");
  309.             if(pa®_IY) strcat(pos,"REG_IY ");
  310.         }
  311.     }
  312.     else if(pa&BRA)
  313.     {
  314.         if(!( (pa & BRANCH8) ^ BRANCH8))
  315.             strcat(pos, "BRA8  ");
  316.         else if(!( (pa & BRANCH8) ^ BRANCH4))
  317.             strcat(pos, "BRA4  ");
  318.         else
  319.         {
  320.             if(pa&BRA_Z )  strcat(pos,"BRA_Z  ");
  321.             if(pa&BRA_NZ)  strcat(pos,"BRA_NZ ");
  322.             if(pa&BRA_C )  strcat(pos,"BRA_C  ");
  323.             if(pa&BRA_NC)  strcat(pos,"BRA_NC ");
  324.             if(pa&BRA_PO)  strcat(pos,"BRA_PO ");
  325.             if(pa&BRA_PE)  strcat(pos,"BRA_PE ");
  326.             if(pa&BRA_P )  strcat(pos,"BRA_P  ");
  327.             if(pa&BRA_M )  strcat(pos,"BRA_M  ");
  328.         }
  329.     }
  330.     if(pa&IND    )
  331.         strcat(pos,"IND     ");
  332.     if(pa&UNM3    )
  333.         strcat(pos,"U3     ");
  334.     if(pa&UNM8    )
  335.         strcat(pos,"U8   ");
  336.     if(pa&UNM16    )
  337.         strcat(pos,"U16  ");
  338.     if(pa&OFF    )
  339.         strcat(pos,"OFF     ");
  340.  
  341.     if(pa&RST    )
  342.         strcat(pos,"RST     ");
  343.     if(pa&JMPREL    )
  344.         strcat(pos,"JMPR ");
  345.  
  346.  
  347.     if(! ((pa&IMODE2)^IMODE0))
  348.         strcat(pos,"IMODE0 ");
  349.     if(! ((pa&IMODE2)^IMODE1))
  350.         strcat(pos,"IMODE1 ");
  351.     if(! ((pa&IMODE2)^IMODE2))
  352.         strcat(pos,"IMODE2 ");
  353.  
  354.     fprintf(stderr,"%s:%s\n",str,pos);
  355. }
  356.  
  357. /*
  358. static int prtallcmd()
  359. {
  360.     struct command *pcmd;
  361.     char par1[BUFSIZ],par2[BUFSIZ];
  362.  
  363.     if(debugf)  puts("prtallcmd");
  364.  
  365.     pcmd = cmd;
  366.     while(pcmd->name)
  367.     {
  368.         par1[0] = par2[0] = '\0';
  369.         fprintf(stderr,"MNE:%s | %s , %s | LE:%X | BY:%d BI:%d , BY:%d BI:%d | %X %X %X %X\n",
  370.                 pcmd->name,
  371.                 decodearg(pcmd->pa1,par1),
  372.                 decodearg(pcmd->pa2,par2),
  373.                 MNELEN(pcmd->order1),
  374.                 BYTE(pcmd->order1),BIT(pcmd->order1),
  375.                 BYTE(pcmd->order2),BIT(pcmd->order2),
  376.                 pcmd->obj[0],pcmd->obj[1],pcmd->obj[2],pcmd->obj[3]);
  377.         pcmd++;
  378.     }
  379. }
  380. */
  381.  
  382. static void  cutend(char *pos)
  383. {
  384.     /*
  385.      *    Remove spaces/CR from end of String
  386.      *
  387.      *    No RC
  388.      */
  389.      
  390.     int n;
  391.     char *tmp;
  392.  
  393.     if(debugf)  puts("cutend");
  394.  
  395.     if(!pos)
  396.         INTERNAL_ERROR
  397.  
  398.     n   = strlen(pos);
  399.  
  400.     if(!n)
  401.         return;
  402.  
  403.     tmp = pos + n - 1;
  404.  
  405.     while(n-- && ((isspace(*tmp))||(*tmp=='\n')) )
  406.         *tmp--='\0';
  407. }
  408.  
  409. static char *skipspace(char *pos)
  410. {
  411.     /*
  412.      *    Skip spaces at top of String
  413.      *
  414.      *    Pointer to start of string ,or
  415.      *    NULL if the string only contains spaces
  416.      */
  417.      
  418.     if(debugf)  puts("skipspace");
  419.  
  420.     while( *pos && isspace(*pos) )
  421.         pos++;
  422.  
  423.     if(*pos)
  424.         return(pos);
  425.     else
  426.         return(NULL);
  427. }
  428.  
  429. static void killcomment(char *pos)
  430. {
  431.     /*
  432.      *    Look for a comment token ( ';'  ) and replace it with '\0'.
  433.      *
  434.      *    No RC
  435.      */
  436.     char *comment;
  437.     char *pt1,*pt2;    /* take care that's ';' isn't inside a Text definition */
  438.  
  439.     if(debugf)  puts("killcomment");
  440.  
  441.     if(!(comment=strchr(pos,(int)';')))
  442.         return;     /* No Comment - do nothing */
  443.  
  444.     pt1        =    strchr(pos,(int)'\'');
  445.     pt2        =    strchr(pos,(int)'/');
  446.  
  447.         /* get first TEXT closing char ( / or ' ) */
  448.     if(pt1 && pt2)
  449.         pt1=MIN(pt1,pt2);
  450.     else if(pt2)
  451.         pt1=pt2;
  452.  
  453.     if(pt1 && (comment>pt1) && (pt2 = strchr(pt1 + 1,(int)*pt1)))
  454.         comment = strchr(pt2,(int)';');
  455.  
  456.     if(comment)
  457.         *comment='\0';
  458. }    
  459.  
  460. struct labelitem *getlabel(struct listheader *plabel,char *name)
  461. {
  462.     /*
  463.      *    Search for the label 'name' in label list. 
  464.      *
  465.      *  RC = if 'name' found, a pointer to the item , else
  466.      *       NULL
  467.      */
  468.  
  469.     int n,i;
  470.     struct labelitem *pitem;
  471.     static struct labelitem ad_cnt = {0,TRUE,L_POSITION,"$"};  /* Simulate Address Counter Label */
  472.  
  473.     if(debugf)  puts("getlabel");
  474.  
  475.     if( (strlen(name)==1) && (*name == '$'))
  476.     {
  477.         ad_cnt.value = object.actbyte; /* set actual Address Counter */
  478.         return(&ad_cnt);
  479.     }
  480.  
  481.     n = plabel->actitem;                        /* get count of items */
  482.     pitem = (struct labelitem *)plabel->list;    /* get first item */
  483.  
  484.     for(i=0;i<n;i++,pitem++)                    /* check all items */
  485.     {
  486.         if(!(strcmp(name,pitem->name)))            /* compare 'name' with item */
  487.             return(pitem);                        /* Success */
  488.     }
  489.     return(NULL);                                /* Failed */
  490. }
  491.  
  492. static int expandlist(struct listheader *plist)
  493. {
  494.     /*    
  495.      * Increase table size. Delta Increase and old table are specified
  496.      * in struct 'listheader'
  497.      *
  498.      * RC: NULL if OK
  499.      *     SERIOUS if realloc fails
  500.      */
  501.  
  502.     if(debugf)  puts("expandlist");
  503.  
  504.                     /* expand table */
  505.     if(plist->list)
  506.     {
  507.         if(!(plist->list=realloc(plist->list,(plist->newnitem+plist->nitem) * plist->sizeitem )))
  508.         {
  509.             fputs("Can't allocate memory for table\n",stderr);
  510.             return(SERIOUS);
  511.         }
  512.     } 
  513.     else
  514.     {    
  515.         if(!(plist->list=malloc(plist->newnitem * plist->sizeitem)))
  516.         {
  517.             fputs("Can't allocate memory for table\n",stderr);
  518.             return(SERIOUS);
  519.         }
  520.     }
  521.     
  522.     plist->nitem += plist->newnitem;    /* actualize count of tableitems */
  523.  
  524.     return(NULL);
  525. }
  526.  
  527. static struct labelitem *insertlabel(struct listheader *plabel,char *name,int type,u_short value,BOOL valid)
  528. {
  529.     /*
  530.      *    Insert a new item in list.
  531.      *
  532.      *    RC:    Pointer to new list element, or
  533.      *        SERIOUS if expandlist() failed
  534.      */
  535.      
  536.     struct labelitem *pitem;
  537.  
  538.     if(debugf)  puts("insertlabel");
  539.  
  540.     if(plabel->actitem >= plabel->nitem)
  541.         if(expandlist(plabel))
  542.             return((struct labelitem*)SERIOUS);
  543.  
  544.     pitem = (struct labelitem *)plabel->list + plabel->actitem;    
  545.     strcpy(pitem->name,name);
  546.     pitem->type = type;
  547.     if(pitem->valid = valid)
  548.         pitem->value = value;
  549.     else
  550.         pitem->value = 0xFFFF;
  551.     (plabel->actitem)++;
  552.  
  553.     return(pitem);
  554. }
  555.  
  556. static int dolabel(struct listheader *plabel,struct objsize *pobjcode,char   *lname)
  557. {
  558.     /*
  559.      * Search for a label. 'pline' must point to supposed label without append ':'.
  560.      * Insert label name and it's objectcode position in list 'label'.
  561.      *
  562.      *    An error can occure in some of the follwing conditions:
  563.      *      if -    the name is too long (MAXLABEL),
  564.      *            declared twice, 
  565.      *            declared before any objectcode adress is set
  566.      *
  567.      *     RC: NULL if all went fine, else
  568.      *        ERROR if any described error ocured, or
  569.      *        SERIOUS if insertlabel() failed
  570.      */
  571.  
  572.     if(debugf)  puts("dolabel");
  573.  
  574.     if(strlen(lname)>MAXLABEL)
  575.     {
  576.         showerror(lname,LABEL_TOO_LONG,MAXLABEL);
  577.         return(ERROR);    
  578.     }
  579.  
  580.     if(getlabel(plabel,lname))
  581.     {
  582.         showerror(lname,LABEL_DECL_TWICE);
  583.         return(ERROR);    
  584.     }
  585.  
  586.     if(pobjcode->firstbyte == ERROR)        
  587.     {
  588.         showerror(lname,NO_ORG);
  589.         return(ERROR);    
  590.     }
  591.         /* insert label item in list */
  592.     if((int)insertlabel(plabel,lname,L_POSITION,(u_short)pobjcode->actbyte,TRUE) == SERIOUS)
  593.         return(SERIOUS);
  594.     else
  595.         return(NULL);
  596. }
  597.  
  598. static int finddirective(char *pos)
  599. {
  600.     /*
  601.      * compare 'pos' with all directives 
  602.      *
  603.      * RC: indize of directive, or
  604.      *     ERROR if not found
  605.      */
  606.  
  607.     int i;
  608.  
  609.     if(debugf)  puts("finddirective");
  610.  
  611.     i=-1;
  612.     while(directives[++i])        /* determine directive type */
  613.     {
  614.         if(!stricmp(directives[i],pos))
  615.             return(i);
  616.     }
  617.     return(ERROR);
  618. }
  619.  
  620. static struct command *findmne(struct command *pcmd,char *pmne)
  621. {
  622.     /*
  623.      *    Compare 'pmne' with Mnemomics. Starts at 'pcmd'.
  624.      *
  625.      *    RC: Pointer to command structure or
  626.      *        NULL if nothing found.
  627.      */
  628.      
  629.     if(debugf)  puts("findmne");
  630.  
  631.     while(pcmd->name && stricmp(pcmd->name,pmne) )    /* search token in 'command' array */
  632.         pcmd++;
  633.  
  634.     if(!pcmd->name)    
  635.         return(NULL);        /* sorry nothing found */
  636.     else
  637.         return(pcmd);
  638. }
  639.  
  640. int strtoint(struct listheader *plabel,char *pstr,u_short *pu_short,int mode)
  641. {
  642.     /*
  643.      *    Convert 'pos' to a u_short. 'pos' could be a value , with one of the 
  644.      *  following Syntax:
  645.      *        - binary      : % at the beginning or b/B at the end 
  646.      *        - octal       : o/O at the end
  647.      *        - decimal     : without any special character or d/D at the end
  648.      *        - hexadecimal : x/X/0x/0X/# at the beginning or h/H at the end 
  649.      *      - $           : Address Counter
  650.      *  Or 'pos' could be a symbol name (constant definition) - so substitute them.
  651.      *
  652.      *  RC : NULL if the substitution were successfully
  653.      *       ERROR else
  654.      */ 
  655.      
  656.     char *tail,work[BUFSIZ],*pos;
  657.     int len,base=0,tmp=0,extension=FALSE;
  658.     struct labelitem *pitem;
  659.  
  660.     if(debugf)  puts("strtoint");
  661.  
  662.     strcpy(work,pstr);
  663.     pos = work;
  664.  
  665.     if(!(len=strlen(pos)))    /* a zerolength word is wrong Parameter */
  666.         return(ERROR);
  667.  
  668.     if( strpbrk(pos,"+-*/()"))    /* mathematical expression ? */
  669.     {
  670.         tmp = calcexpr(plabel,pos,pu_short);
  671.  
  672.         if(mode==PARSE2)
  673.             return(tmp);
  674.         else
  675.             return(NULL);
  676.     }
  677.  
  678.         /* Is there an ASCII char ? */
  679.     if(*pos=='\'' || *pos=='/')
  680.     {
  681.         if(pos[0]==pos[2])    /* must be quoted like '?' or /?/ */
  682.         {
  683.             *pu_short=(u_short)pos[1];
  684.             return(NULL);
  685.         }
  686.     }
  687.  
  688.     if(pitem=getlabel(plabel,pos))    /* is the word a label ? */
  689.     {
  690.         if(mode == PARSE2)
  691.         {
  692.             if(!(pitem->valid))
  693.                 return(ERROR);    /* Label exist, but is invalid */
  694.         }
  695.         *pu_short = pitem->value;
  696.         return(NULL);
  697.     }
  698.     
  699.     if(len==1)                /* length =1 -> must be a decimal value */
  700.     {
  701.         if(!isdigit(*pos))    /* value ? */
  702.             return(ERROR);    /*  NO, so no number (perhaps a Register)*/
  703.     }
  704.  
  705.     switch(pos[len-1])                /* are there any known extensions ? */
  706.     {
  707.         case 'b':       /* A 'b' at the end could also be be a HEX 'b': check this */
  708.         case 'B': if( toupper(pos[0])=='X' || ( (pos[0]=='0') && (toupper(pos[1])=='X')) ) 
  709.                   {
  710.                     base = 16;  
  711.                     tmp = 2;
  712.                   }
  713.                   else  
  714.                   {
  715.                       extension=TRUE;
  716.                     base = 2;
  717.                   }
  718.                   break;    
  719.         case 'o':
  720.         case 'O': base = 8;
  721.                   extension=TRUE;
  722.                   break;    
  723.         case 'h':
  724.         case 'H': base = 16;
  725.                   extension=TRUE;
  726.                   break;    
  727.     }
  728.  
  729.     
  730. #ifdef DEBUG_STRTOINT
  731.     if(base)
  732.         fprintf(stderr,"strtoint(): base=%d\n",base);
  733. #endif
  734.  
  735.     if(!base)                            
  736.     {                                /* no extensions found, so look at the beginning */
  737.         switch(pos[0])
  738.         {
  739.             case '#' :    
  740.             case 'x' : 
  741.             case 'X' :     base = 16;
  742.                            tmp = 1;    
  743.                            break;
  744.             case '0' :     if( pos[1] == 'x' || pos[1] == 'X')
  745.                            {
  746.                                base = 16;
  747.                                tmp = 2;
  748.                            }
  749.                            break;
  750.             case '%' :    base = 2;
  751.                         tmp = 1;
  752.                         break;
  753.             default     :     if(toupper(pos[len-1])=='B')
  754.                             base = 2;
  755.                         break;    
  756.         }
  757.     }
  758.     
  759.     if(extension)
  760.         pos[--len]='\0';            /* cut the extension */
  761.  
  762.     if(!base) 
  763.         base = 10;                    /* no base specified -> decimal is assumed */
  764.  
  765. #ifdef DEBUG_STRTOINT
  766.     fprintf(stderr,"strtoint(): base=%d, number=%s\n",base,&pos[tmp]);
  767. #endif
  768.  
  769.     if(!(*pu_short=(u_short)strtol(&pos[tmp],&tail,base)))    /* convert */
  770.     {
  771.         while(tmp<len)                /* NULL -> there could be a failure */
  772.         {
  773.             if(pos[tmp++]!='0')        /* if one char is not 0, that's a failure */
  774.                 return(ERROR);    
  775.         }
  776.     }
  777.     return(NULL);                    /* all went fine */
  778. }
  779.  
  780. static u_long argtype(struct listheader *plabel,char *pos,u_short *pu_short,int mode)
  781. {
  782.     /*
  783.      *    Check type of 'pos' and fill 'pu_short' with data.
  784.      *
  785.      *a)pos= numeric value => set pu_short to value
  786.      *  pos= constant definition => set pu_short to value of constant
  787.      *  pos= numeric expression  => set pu_short to result of expression
  788.      *
  789.      *b)pos is enclosed in brackets: => pos is 'IND'
  790.      *  pos is a 16-Bit Register
  791.      *  all other like a)
  792.      *
  793.      *c)pos (with or without 'IND') is IX,IY with '+' Offset, set OFF.
  794.      *  calculate Offset like an expression in a)
  795.      *
  796.      *    RC: Parameter type of 'pos', or
  797.      *        NULL if not found.
  798.      */
  799.     
  800.     u_long flag = 0L;
  801.     int  len;
  802.     char *poff,work[BUFSIZ],*pwork;
  803.  
  804.     if(debugf)  puts("argtype");
  805.  
  806.     strcpy(work,pos);
  807.     pwork=work;
  808.     
  809.     cutend(pwork);                            /* remove trailing spaces */
  810.     if(work[0] == '(')                            /* could it be indirekt ? */
  811.     {
  812.         len=strlen(work);
  813.         if( work[len-1] != ')'  )    /* look for closing bracket */
  814.         {
  815.             showerror(pos+len-1,NO_CLOSE_BRACKET);
  816.             return(NULL);    
  817.         }
  818.  
  819.         work[len-1] = '\0';            /* delete end bracket from String */
  820.         cutend(pos);                /* remove trailing spaces */
  821.  
  822.         if(!(pwork=skipspace(&pwork[1])))/* skip start bracket and leading spaces */
  823.         {
  824.             showerror(pos,NO_EXPR_INSIDE);
  825.             return(NULL);
  826.         }
  827.         flag |= IND;                        /* remark INDIREKT        */
  828. #ifdef DEBUG2
  829.     fprintf(stderr,"Argument:'%s' is Indirekt, work continued with:'%s'\n",pos,pwork); 
  830. #endif
  831.     }
  832.  
  833.     if(poff=strchr(pwork,'+'))                /* look for an offset */
  834.     {
  835.         *poff='\0';
  836.         cutend(pwork);
  837.         if(!stricmp(pwork,"IX"))
  838.            flag|=REG_IX|OFF;
  839.         else if(!stricmp(pwork,"IY"))
  840.            flag|=REG_IY|OFF;
  841.         else
  842.         {    /* No Offset expression, so restore all */
  843.             strcpy(work,pos);
  844.             if(flag&IND)
  845.             {
  846.                 pwork=skipspace(&work[1]);
  847.                 work[strlen(work)-1]='\0';
  848.                 cutend(pwork);
  849.             }
  850.             else
  851.                 pwork = work;
  852.         }
  853.         if(flag&OFF)
  854.             if(!(pwork=skipspace(poff+1)))
  855.             {
  856.                 showerror(pos,NO_EXPR_FOLLOWED);
  857.                 return(NULL);
  858.             }
  859.     }
  860.  
  861.         /* Check if it's an integer (or Label - substitute them) */
  862.     if(!strtoint(plabel,pwork,pu_short,mode))    /* Integer, so check the size */
  863.     {
  864.         if(debugv) fprintf(stderr,"partype: ARG:%s VALUE:%d\n",pwork,*pu_short);
  865.  
  866.         flag|=NBR|UNM16|UNM8|UNM3|RST;            /* set No Branch */
  867.         if(*pu_short > 255) 
  868.             flag &= ~(UNM8|UNM3|RST); 
  869.         else if(*pu_short > 7  ) 
  870.             flag &= ~UNM3; 
  871.         else
  872.         {
  873.             switch(*pu_short)        /* needed for Mnemomic 'IM 0/1/2' */
  874.             {
  875.                 case 0: flag|=IMODE0; break;
  876.                 case 1: flag|=IMODE1; break;
  877.                 case 2: flag|=IMODE2; break;
  878.             }
  879.         }
  880.             /* check if is Offset < 256 */
  881.         if( (flag&OFF) && (*pu_short>255))
  882.         {
  883.             showerror(pos,OFFSET_OUT_OF_RANGE);
  884.             return(NULL);
  885.         }
  886.     }
  887.  
  888.     if(!(flag&~IND)) /* Until yet nothing found -> check if it is a Register/Branch */
  889.     {
  890.         *pwork = toupper(*pwork);
  891.         len  = strlen(pwork);
  892.  
  893.         switch(len)
  894.         {
  895.         case 1:
  896.             switch(*pwork)
  897.             {
  898.                 case 'A': flag |= REG_A|NBR; break;
  899.                 case 'B': flag |= REG_B|NBR; break;
  900.                 case 'C': flag |= REG_C|NBR|BRA; break;
  901.                 case 'D': flag |= REG_D|NBR; break;
  902.                 case 'E': flag |= REG_E|NBR; break;
  903.                 case 'F': flag |= REG_F|NBR; break;
  904.                 case 'H': flag |= REG_H|NBR; break;
  905.                 case 'I': flag |= REG_I|NBR; break;
  906.                 case 'L': flag |= REG_L|NBR; break;
  907.                 case 'M': flag |= BRA_M|BRA; break;
  908.                 case 'P': flag |= BRA_P|BRA; break;
  909.                 case 'R': flag |= REG_R|NBR; break;
  910.                 case 'Z': flag |= BRA_Z|BRA; break;
  911.                 default:     showerror(pos,UNKNOWN_OPTION);
  912.                             return(NULL);    
  913.             }
  914.             break;
  915.  
  916.         case 2:
  917.             pwork[1] = toupper(pwork[1]);
  918.             switch(pwork[0])
  919.             {
  920.                 case 'A':    if( pwork[1]=='F' ) flag |= REG_AF|NBR; else flag=ERROR; break;
  921.                 case 'B':     if( pwork[1]=='C' ) flag |= REG_BC|NBR; else flag=ERROR; break;
  922.                 case 'D':     if( pwork[1]=='E' ) flag |= REG_DE|NBR; else flag=ERROR; break;
  923.                 case 'H':     if( pwork[1]=='L' ) flag |= REG_HL|NBR; else flag=ERROR; break;
  924.                 case 'I':     if( pwork[1]=='X' ) flag |= REG_IX|NBR; else 
  925.                             if( pwork[1]=='Y' ) flag |= REG_IY|NBR; else flag=ERROR; break;
  926.                 case 'N':     if( pwork[1]=='C' ) flag |= BRA_NC|BRA; else 
  927.                             if( pwork[1]=='Z' ) flag |= BRA_NZ|BRA; else flag=ERROR; break;
  928.                 case 'P':     if( pwork[1]=='O' ) flag |= BRA_PO|BRA; else 
  929.                             if( pwork[1]=='E' ) flag |= BRA_PE|BRA; else flag=ERROR; break;
  930.                 case 'S':     if( pwork[1]=='P' ) flag |= REG_SP|NBR; else flag=ERROR; break;
  931.                 default:     showerror(pos,SYNTAX_ERROR);
  932.                             return(NULL);    
  933.             }
  934.             break;
  935.         
  936.         default: if(mode==PARSE1)
  937.                     return(flag|UNM16|UNM8|UNM3|NBR);
  938.                  else
  939.                  {
  940.                     showerror(pos,UNKNOWN_ARG);
  941.                     return(NULL);
  942.                  }
  943.         }
  944.     }
  945.     if(!flag)        
  946.         flag=NOPAR;    /* no flag -> NOPAR */
  947.  
  948.     return(flag);
  949. }
  950.  
  951. static int doobjadr(struct objsize *pobj,int n,int mode)
  952. {
  953.     /*
  954.      *    Set virtual objectbuffer position.
  955.      *
  956.      *    RC: NULL if all went fine, else
  957.      *        ERROR if 'n' < 0 or 
  958.      *              'mode' == OBJADREL && pobj->firstbyte == ERROR
  959.      */
  960.  
  961.     if(debugf)  puts("doobjadr");
  962.  
  963.     if(n < 0)
  964.     {
  965.         fprintf(stderr,"Internal ERROR.  LINE=%d\nObject Adress %d corrupt (mode=%s)",__LINE__,n,(mode==OBJADABS) ? "OBJADABS" : "OBJADREL");
  966.         return(ERROR);
  967.     }
  968.  
  969.     switch(mode)
  970.     {
  971.         case OBJADABS:    if(pobj->firstbyte == ERROR)
  972.                         {
  973.                             pobj->firstbyte = n;
  974.                             pobj->actbyte   = n;
  975.                             pobj->lastbyte  = n;
  976.                             break;
  977.                         }
  978.                         else if (pobj->firstbyte >= n)
  979.                         {
  980.                             pobj->firstbyte = n;
  981.                             pobj->actbyte   = n;
  982.                             break;
  983.                         }
  984.                         else if (pobj->firstbyte < n)
  985.                         {
  986.                             pobj->actbyte   = n;
  987.                             if (pobj->lastbyte < n)
  988.                                 pobj->lastbyte   = n;
  989.                             break;
  990.                         }
  991.                         else 
  992.                             INTERNAL_ERROR
  993.                         break;
  994.         case OBJADREL:    if(pobj->firstbyte == ERROR)
  995.                         {
  996.                             showerror(work,NO_ORG);
  997.                             return(ERROR);
  998.                         }
  999.                         pobj->actbyte += n;
  1000.                         if(pobj->actbyte > pobj->lastbyte)
  1001.                             pobj->lastbyte = pobj->actbyte;
  1002.                         break;
  1003.         default:        INTERNAL_ERROR
  1004.                         return(ERROR);
  1005.     }
  1006.     return(NULL);
  1007. }
  1008.  
  1009. static u_char codebits(u_long mask)
  1010. {
  1011.     u_char code=0;
  1012.  
  1013.     if(debugf)  puts("codebits");
  1014.  
  1015.     if(mask&BRA)
  1016.     {
  1017.         switch(mask&BRANCH8)
  1018.         {
  1019.             case BRA_NZ    : code = 0; break;
  1020.             case BRA_Z    : code = 1; break;
  1021.             case BRA_NC    : code = 2; break;
  1022.             case BRA_C    : code = 3; break;
  1023.             case BRA_PO    : code = 4; break;
  1024.             case BRA_PE    : code = 5; break;
  1025.             case BRA_P    : code = 6; break;
  1026.             case BRA_M     : code = 7; break;
  1027.             default        : INTERNAL_ERROR
  1028.         }
  1029.     }
  1030.     else if(mask&NBR)
  1031.     {
  1032.         switch(mask®)
  1033.         {
  1034.             case REG_A    : code = 7; break;
  1035.             case REG_B    : code = 0; break;
  1036.             case REG_C    : code = 1; break;
  1037.             case REG_D    : code = 2; break;
  1038.             case REG_E    : code = 3; break;
  1039.             case REG_H    : code = 4; break;
  1040.             case REG_L    : code = 5;    break;
  1041.  
  1042.             case REG_BC    : code = 0; break;
  1043.             case REG_DE    : code = 1; break;
  1044.             case REG_HL    : code = 2; break;
  1045.             case REG_SP    : code = 3; break;
  1046.  
  1047.             case REG_F    :
  1048.             case REG_I    :
  1049.             case REG_R    :
  1050.             case REG_AF    :
  1051.             case REG_IX    :
  1052.             case REG_IY    : code = 0; 
  1053.                           INTERNAL_ERROR    
  1054.                           break;
  1055.             default        : code = 0;
  1056.                           INTERNAL_ERROR
  1057.         }
  1058.     }
  1059.     else 
  1060.         INTERNAL_ERROR      
  1061.  
  1062.     return(code);
  1063. }
  1064.  
  1065. static int writemnedata(struct objsize *pobj,u_long maskarg,u_short val,u_long maskcmd,u_char pos)
  1066. {
  1067.     /*
  1068.      *    Write coded Data to Objectbuffer.
  1069.      *
  1070.      *    -Calculate adress of byte of objectbuffer.
  1071.      *    -If 'maskcmd' is UNM16, write a Word in Lo/Hi order .
  1072.      *    -If 'maskcmd' is UNM8, write a Byte. 
  1073.      *    -If 'maskcmd' is bit coded , determine bit position and write.
  1074.      *
  1075.      *    RC:    NULL if all went fine , else
  1076.      *        ERROR
  1077.      */
  1078.      
  1079.     u_char *tmpobj,code=0;
  1080.     int off;
  1081.  
  1082.     if(debugf)  puts("writemnedata");
  1083.  
  1084. #    ifdef DEBUG2
  1085.         fprintf(stderr,"--- pos:%X\n",pos);
  1086. #    endif
  1087.  
  1088.     if(NOE & pos)
  1089.         return(NULL);
  1090.  
  1091.     tmpobj = ACT_OBJ_ADDR(pobj) + BYTE(pos);
  1092.  
  1093.     if(maskarg&maskcmd&UNM16)
  1094.     {
  1095.         if(maskcmd&JMPREL)            /* UNM16 only set to generate jmp offset */
  1096.         {
  1097.             off=val - pobj->actbyte-2;    /* Destination - Source */
  1098.             if( off>129 || off<-126)    /* jmp not to big ? */
  1099.             {
  1100.                 showerror(NULL,JUMP_NOT_RANGE);
  1101.                 return(ERROR);
  1102.             }
  1103.             *tmpobj=(char)off; 
  1104.             return(NULL);
  1105.         }
  1106.         else
  1107.         {
  1108.             *tmpobj++ = LOBYTE(val);    /* write LO Byte */
  1109.             *tmpobj   = HIBYTE(val);    /* write HI Byte */
  1110.             return(NULL);
  1111.         }
  1112.     } 
  1113.     if(maskcmd & RST)
  1114.     {
  1115.         code= val & 0x38;    /* extract RST bits */        
  1116.         if(code^(u_char)val)
  1117.         {
  1118.             showerror(NULL,ILLEGAL_RST);
  1119.             return(ERROR);
  1120.         }
  1121.         *tmpobj |= (code>>3)<<BIT(pos);
  1122.         return(NULL);
  1123.     } 
  1124.     
  1125.     if( (maskarg&maskcmd)&(UNM8|OFF) )
  1126.     {
  1127.         *tmpobj=(u_char)val;    /* write Byte */
  1128.         return(NULL);
  1129.     }
  1130.     if( maskcmd&maskarg&UNM3)
  1131.         code = (u_char)val;
  1132.     else
  1133.         code = codebits(maskarg);
  1134.  
  1135.     *tmpobj |= code<<BIT(pos);
  1136.  
  1137.     return(NULL);
  1138. }
  1139.  
  1140. static int fillihbuffer(int addr,int nbytes,u_char *pbuf)
  1141. {
  1142.     /*
  1143.      * Make a complete row in INTELHEX format.
  1144.      * Code: ':nnaaaadddd...dddcc\n
  1145.      * Where: nn        - number of data bytes
  1146.      *        aaaa        - address
  1147.      *        dd..dd    - data bytes
  1148.      *        cc        - checksum = 0x100 - (aa + aa + nn + dd + .. + dd)
  1149.      * Everything is in ASCII, 'intelhexbuffer' is dynamically allocated.
  1150.      *
  1151.      * RC: NULL if all went fine,
  1152.      *       ERROR else.
  1153.      */
  1154.  
  1155. #define NCTRLBYTES    12 /* :nnaaaasspp\n = 12 */
  1156.  
  1157.     int datasum;
  1158.     char *pos;
  1159.  
  1160.     if(debugf)  puts("fillihbuffer");
  1161.  
  1162.     if(!nbytes)
  1163.     {
  1164.         fprintf(stderr,"Internal ERROR: nbytes=0  LINE=%d\n",__LINE__);
  1165.         return(ERROR);
  1166.     }
  1167.     
  1168.         /* take care to have enough space */
  1169.     if(ih_head.actitem+nbytes*2+NCTRLBYTES >= ih_head.nitem)
  1170.     {
  1171.         if(expandlist(&ih_head))
  1172.             return(SERIOUS);    /* should never be happen */
  1173.     }
  1174.         /* next free Position */
  1175.     pos=(char *)(((char *)ih_head.list)+ih_head.actitem);
  1176.  
  1177.     *pos++=':';                                 /* Set Start Marker */
  1178.     pos = ibtoh(nbytes,pos);                     /* Write data counter */
  1179.     pos = ibtoh((unsigned char)(addr>>8),pos);      /* Write High Byte Address */
  1180.     pos = ibtoh((unsigned char)(0xFF&addr),pos); /* Write Low Byte Address */
  1181.     pos = ibtoh((u_char)0,pos);                     /* Write status */
  1182.  
  1183.     datasum=(0xFF&(addr>>8))+(0xFF&addr)+nbytes; /* part of chksum */
  1184.  
  1185.     while(nbytes--)
  1186.     {
  1187.         datasum+=(int)*pbuf;
  1188.         pos = ibtoh(*pbuf++,pos);            /* Write databyte */
  1189.     }
  1190.  
  1191.     datasum=0x100-(0xFF&datasum);            /* finish chksum */
  1192.     pos = ibtoh((u_char)datasum,pos);        /* Write chksum */
  1193.     *pos++ = '\n';                            /* Close String */
  1194.     *pos = '\0';                            /* Close String */
  1195.  
  1196.     ih_head.actitem=(int)pos-(int)ih_head.list;
  1197.  
  1198.     return(NULL);
  1199. }
  1200.  
  1201. static int dointelhex(int addr,int size,u_char *data)
  1202. {
  1203.     /*
  1204.      *    Collect Data to generate INTELHEX Format.
  1205.      *  Collect a row (Maximum Databytes = MAXBYTESIH).
  1206.      *    If the row is full or is there a skip in addressing
  1207.      *   call 'fillihbuffer()' to flush buffer.
  1208.      *
  1209.      *    RC:    NULL if all went fine,
  1210.      *        ERROR else.
  1211.      */
  1212.      
  1213.     static int rowaddr=ERROR,rownbytes=0;
  1214.     static u_char rowdata[MAXBYTESIH];
  1215.  
  1216.     u_char *prowdata;
  1217.  
  1218.     if(debugf)  puts("dointelhex");
  1219.  
  1220.         /* Flush Buffer, write ENDLINE */
  1221.     if(addr==ERROR)
  1222.     {
  1223.         if(rownbytes)
  1224.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1225.             
  1226.             /* take care to have enough space */
  1227.         if(ih_head.actitem+13 >= ih_head.nitem)
  1228.         {
  1229.             if(expandlist(&ih_head))
  1230.                 return(SERIOUS);    /* should never be happen */
  1231.         }
  1232.         strcpy((char *)ih_head.list+ih_head.actitem,":00000001FF\n");
  1233.         ih_head.actitem+=12;
  1234.         rowaddr=ERROR;
  1235.         rownbytes=0;
  1236.         return(NULL);
  1237.     }
  1238.     
  1239.         /* If 'addr' not continous, start a new row */
  1240.     if(addr!=(rowaddr+rownbytes))
  1241.     {
  1242.         if((rowaddr!=ERROR) && (rownbytes))
  1243.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1244.         rowaddr=addr;
  1245.         rownbytes=0;
  1246.     }
  1247.  
  1248.     while(size)
  1249.     {
  1250.         prowdata=&rowdata[rownbytes];
  1251.         
  1252.             /* fill data in 'rowdata' */
  1253.         while(    (rownbytes<MAXBYTESIH) && size)
  1254.         {
  1255.             size--;
  1256.             rownbytes++;
  1257.             *prowdata++=*data++;
  1258.         }
  1259.  
  1260.             /* row full ? */
  1261.         if(rownbytes>=MAXBYTESIH)
  1262.         {
  1263.                 /* finish row, open new */
  1264.             fillihbuffer(rowaddr,rownbytes,rowdata);
  1265.             rowaddr+=rownbytes;
  1266.             rownbytes=0;
  1267.         }
  1268.     }
  1269.     return(NULL);
  1270. }
  1271.  
  1272. static int makecode(struct objsize *pobj,struct command *pcmd,int mode,u_long type1,u_short val1,u_long type2,u_short val2)
  1273. {
  1274.     /*
  1275.      *    If mode==PARSE1 then
  1276.      *        calculate object size and increase 'pobj'
  1277.      *    If mode==PARSE2
  1278.      *        Generates Object Code and write it to objbuffer
  1279.      *     
  1280.      *    RC:    NULL if all went fine, else
  1281.      *        ERROR 
  1282.      */
  1283.      
  1284.     int size,i;
  1285.     u_char dummy;
  1286.  
  1287.     if(debugf)  puts("makecode");
  1288.  
  1289.     size = MNELEN(pcmd->order1);                /* How much Bytes to write */
  1290.  
  1291.     if(mode==PARSE1)
  1292.     {
  1293.         return(doobjadr(pobj,size,OBJADREL));    /* Only increase Objectbuffer */
  1294.     }
  1295.     else if(mode==PARSE2)
  1296.     {
  1297.         for(i=0;i<size;i++)                        
  1298.         {
  1299.             if(dummy=*(ACT_OBJ_ADDR(pobj)+i) )
  1300.             {
  1301.                 showerror(NULL,DATA_OVERWRITE);
  1302.                 return(ERROR);
  1303.             }
  1304.             *(ACT_OBJ_ADDR(pobj)+i)=pcmd->obj[i];    /* copy Object Code */
  1305.         }
  1306.  
  1307. #        ifdef DEBUG2
  1308.             fprintf(stderr,"pcmd[%d]\n",(int)((char *)pcmd-(char *)cmd)/sizeof(struct command));
  1309.             fprintf(stderr,"---pcmd->order1:%X\n",pcmd->order1);
  1310. #        endif
  1311.  
  1312.         writemnedata(pobj,type1,val1,pcmd->pa1,pcmd->order1);    /* set Register/Branch Bits (Argu.1)*/
  1313.  
  1314. #       ifdef DEBUG2
  1315.             fprintf(stderr,"---pcmd->order2:%X\n",pcmd->order2);
  1316. #       endif
  1317.  
  1318.         writemnedata(pobj,type2,val2,pcmd->pa2,pcmd->order2);    /* set Register/Branch Bits (Argu.2)*/
  1319.  
  1320.         if(doobjadr(pobj,size,OBJADREL))            /* increase Objectbuffer */
  1321.             return(ERROR);
  1322.     }
  1323.     else
  1324.         INTERNAL_ERROR;
  1325.  
  1326.     return(NULL);
  1327. }
  1328.  
  1329. static int domne(struct listheader *plabel,struct objsize *pobj,char *ptok,int mode,u_short *pcycle)
  1330. {
  1331.     /*     
  1332.      *    Search for mnemomic 'ptok'.
  1333.      *    First compare mnemomic name 
  1334.      *    Check arguments (if they are allowed) 
  1335.      *    if mode==PARSE1
  1336.      *        increase 'pobj' about the size of mnemomic
  1337.      *    else if mode==PARSE2
  1338.      *        fill objbuffer with generated code
  1339.      *
  1340.      *    RC: NULL if a mnemomic was found, regardless if the parsing for successfully
  1341.      *      ERROR if no mnemomic was found
  1342.      */
  1343.  
  1344.     struct command *pcmd;    /* Pointer to actual MNE in 'caz' MNE-Array */
  1345.     char     *ptok2,            /* second Argument */
  1346.             *pend,            /* points behind last Argument (for missing arguments)*/
  1347.             *pmne;            /* points to Sourcetext MNE */
  1348.     u_long    type1,tmp1,        /* classes of 1. parsed argument */
  1349.             type2,tmp2,        /* classes of 2. parsed argument */
  1350.             f1,f2,f3,f4;    /* just for debugv */
  1351.     u_short    val1,val2;        /* if 1./2. argument is a value */
  1352.     
  1353.             /* Just to report more detailed Error Messages */
  1354.     int        arg1_ex,arg2_ex,    /* Flag if MNE need Argument1,Argumnt2 */
  1355.             arg1_nex,arg2_nex,    /* Flag if MNE don't need Argument1,Argument2 */
  1356.             arg1_ok,arg2_ok;    /* Flag if MNE Arguments and Sourcetext Arguments match */
  1357.     
  1358.     arg1_ex=arg2_ex=arg1_nex=arg2_nex=arg1_ok=arg2_ok=FALSE;
  1359.  
  1360.     if(debugf)  puts("domne");
  1361.  
  1362. #    ifdef DEBUG2
  1363.         u_long fuck1,fuck2;
  1364. #    endif
  1365.  
  1366.     pmne = ptok;                /* Mnemomic Name */
  1367.     type1 = type2 = NOPAR;
  1368.  
  1369.         /* check all appropriate prozessor mnemomics */
  1370.     if(pcmd=findmne(cmd,pmne))
  1371.     {
  1372.             /* get Arguments (type) and their value (if they have one) */
  1373.         if(ptok=strtok(NULL,","))
  1374.         {
  1375.             ptok=skipspace(ptok);
  1376.             if(ptok2=strtok(NULL,"\n"))
  1377.             {
  1378.                 ptok2=skipspace(ptok2);
  1379.                 type2=argtype(plabel,ptok2,&val2,mode);
  1380.                 pend = ptok2+strlen(ptok2);
  1381.             }            
  1382.             else
  1383.                 pend = ptok+strlen(ptok);
  1384.             
  1385.             type1=argtype(plabel,ptok,&val1,mode);
  1386.         }
  1387.         else
  1388.             pend = pmne+strlen(pmne);
  1389.  
  1390.         tmp1 = type1; /* saved to restore */
  1391.         tmp2 = type2; /* saved to restore */
  1392.         do {
  1393.                 /* Just to report more detailed Error Messages */ 
  1394.             if(pcmd->pa1&NOPAR)
  1395.                 arg1_nex=TRUE;
  1396.             else if(pcmd->pa1&~NOPAR)
  1397.                 arg1_ex=TRUE;
  1398.  
  1399.             if(pcmd->pa2&NOPAR)
  1400.                 arg2_nex=TRUE;
  1401.             else if(pcmd->pa2&~NOPAR)
  1402.                 arg2_ex=TRUE;
  1403.  
  1404.                 /* first delete all flags which not needed */
  1405.             type2&=~IMODE2;
  1406.             
  1407.             if(!(pcmd->pa1&IMODE2))
  1408.                 type1&=~IMODE2;
  1409.                 
  1410.             if(!(pcmd->pa1&BRA))
  1411.             {
  1412.                 type1&=~BRA;
  1413.                 type2&=~BRA;
  1414.             }
  1415.             if(!(pcmd->pa1&NBR))
  1416.             {
  1417.                 type1&=~NBR;
  1418.                 type2&=~NBR;
  1419.             }
  1420.                 /* check if bitpattern match with 'pcmd' */
  1421.             if(debugv)
  1422.             {
  1423.                 decodearg("Type1",type1);
  1424.                 decodearg("Cmd1",pcmd->pa1);
  1425.                 decodearg("Type2",type2);
  1426.                 decodearg("Cmd2",pcmd->pa2);
  1427.                 fputs("\n",stderr);
  1428.             }
  1429.  
  1430. /* There are two types of flags: */
  1431. /* a) flags which must be equal (masked with EXMASK) */
  1432. /* b) flags which could be equal */
  1433.  
  1434.             /* this flags determine the classes */
  1435.             /* f1,f2 are true if the classes matches */
  1436.             f1 = pcmd->pa1&type1&~EXMASK;
  1437.             f2 = pcmd->pa2&type2&~EXMASK;
  1438.  
  1439.             
  1440. #            ifdef DEBUG2
  1441.                 /* This flags must be equal */
  1442.                 fuck1 = pcmd->pa1&EXMASK;
  1443.                 fuck2 = type1&EXMASK;
  1444. #            endif
  1445.  
  1446.             /* if 'f3' is true, the flags differs */
  1447.             f3 = (pcmd->pa1&(EXMASK))^(type1&(EXMASK));
  1448.  
  1449. #           ifdef DEBUG2
  1450.                 /* This flags must be equal */
  1451.                 fuck1 = pcmd->pa2&EXMASK;
  1452.                 fuck2 = type2&EXMASK;
  1453. #           endif            
  1454.             
  1455.             /* if 'f4' is true, the flags differs */
  1456.             f4 = (pcmd->pa2&EXMASK&~(BRA|NBR))^(type2&EXMASK&~(BRA|NBR));
  1457.  
  1458.                 /* Just to report more detailed Error Messages */ 
  1459.             if(f1 &&(!f3))
  1460.                 arg1_ok = TRUE;
  1461.             if(f2 &&(!f4))
  1462.                 arg2_ok = TRUE;
  1463.  
  1464.             if( f1 && f2 && (!f3) && (!f4) )
  1465.             {
  1466. #            ifdef DEBUG2
  1467.                 fprintf(stderr,"--- found:%s,order1:%X\n",pcmd->name,pcmd->order1);
  1468. #            endif
  1469.  
  1470.                 if(!makecode(pobj,pcmd,mode,type1,val1,type2,val2))
  1471.                     *pcycle=pcmd->cycle;        /* copy Clock Cycle */
  1472.                  return(NULL);
  1473.             }
  1474.             type1 = tmp1;
  1475.             type2 = tmp2;
  1476.         } while(pcmd=findmne(++pcmd,pmne));
  1477.  
  1478.     /* This explains the User what's wrong */
  1479.  
  1480.         /* Easier handling if flag NOPAR is cleared */
  1481.         type1&=~NOPAR;
  1482.         type2&=~NOPAR;
  1483.  
  1484. /* All 'arg' - Flags: If True, the condition could be True, but don't have to be True */
  1485.         if(!arg1_ex && !arg2_ex)
  1486.         {  /* No Arguments allowed */
  1487.             if(type1 || type2)
  1488.                 showerror(ptok,TOO_MUCH_ARGUMENT);
  1489.         }
  1490.         else if(arg1_ex && !arg1_nex && !arg2_ex)
  1491.         {  /* exact 1 argument */
  1492.             if(!type1) 
  1493.                 showerror(pend,NEED_ARGUMENT);
  1494.             else if(type2)
  1495.                 showerror(ptok2,TOO_MUCH_ARGUMENT);
  1496.             else
  1497.                 showerror(ptok,WRONG_ARGUMENT);
  1498.         }
  1499.         else if(arg1_ex && !arg1_nex && arg2_ex && !arg2_nex )
  1500.         {  /* exact 2 arguments */
  1501.             if(!type1) 
  1502.                 showerror(pend,NEED_2ARGUMENT);
  1503.             else if(!type2) 
  1504.                 showerror(pend,NEED_A2ARGUMENT);
  1505.             else if(arg1_ok && arg2_ok)
  1506.                 showerror(ptok,W_ARG_COMBINATION);
  1507.             else if(!arg2_ok)
  1508.                 showerror(ptok2,WRONG_ARGUMENT);
  1509.             else if(!arg1_ok)
  1510.                 showerror(ptok,WRONG_ARGUMENT);
  1511.             else 
  1512.                 INTERNAL_ERROR         /* Do I forget a case ? */
  1513.         }
  1514.         else if(arg1_ex && !arg2_ex)
  1515.         {  /* minimal 0 arguments, maximal 1 argument */
  1516.             showerror(ptok,WRONG_ARGUMENT);
  1517.         }
  1518.         else if(!arg1_nex && arg1_ex && arg2_ex )
  1519.         {  /* minimal 1 Argument, maximal 2 arguments */
  1520.             if(!type1)
  1521.                 showerror(pend,NEED_ARGUMENT);
  1522.             else if(type2 && !arg2_ok)
  1523.                 showerror(ptok2,WRONG_ARGUMENT);
  1524.             else
  1525.                 showerror(ptok,WRONG_ARGUMENT);            
  1526.         }
  1527.         else if(arg1_ex && arg2_ex )
  1528.         {  /* minimal 0 arguments, maximal 2 arguments */
  1529.             if(arg1_ok && arg2_ok)
  1530.                 showerror(ptok,W_ARG_COMBINATION);
  1531.             else if(!arg2_ok)
  1532.                 showerror(ptok2,WRONG_ARGUMENT);
  1533.             else if(!arg1_ok)
  1534.                 showerror(ptok,WRONG_ARGUMENT);
  1535.             else
  1536.                 showerror(ptok,WRONG_ARGUMENT);            
  1537.         }
  1538.         else
  1539.             INTERNAL_ERROR         /* Do I forget a case ? */
  1540.         
  1541.         return(NULL);    /* If any MNE was found , rc=NULL */
  1542.     }
  1543.     return(ERROR);        /* If no MNE was found , rc=ERROR */ 
  1544. }
  1545.  
  1546. static int pushfile(struct item_file **pstack,char *p_filenamenew,FILE **p_fp)
  1547. {
  1548.     /* Push item on stack. Set 'pstack' to new top of stack .
  1549.      *
  1550.      * RC: NULL if all went fine,
  1551.      *     ERROR if malloc() failed() or new file can't be opened;
  1552.      */
  1553.      
  1554.     struct item_file *pnode;
  1555.     FILE *fptmp;
  1556.     
  1557.  
  1558.     if(!(fptmp=fopen(p_filenamenew,"r")))
  1559.     {    
  1560.         showerror(p_filenamenew,CANT_OPEN_FILE,p_filenamenew);
  1561.         return(ERROR);
  1562.     }
  1563.  
  1564.     if(!(pnode=(struct item_file *)malloc(sizeof(struct item_file))))
  1565.     {
  1566.         fprintf(stderr,NO_MEMORY);
  1567.         return(ERROR);
  1568.     }
  1569.  
  1570.     pnode->prev = *pstack;
  1571.     strcpy(pnode->filename,actfilename);  /* save old filename (to be push) */
  1572.     strcpy(actfilename,p_filenamenew);      /* set new filename */
  1573.     pnode->filepos = ftell(*p_fp);          /* save old fileposition */
  1574.     pnode->lnr     = lnr;                  /* save old linenumber */
  1575.     *pstack     = pnode;                  /* set new item on top of stack */
  1576.  
  1577.     lnr = 0;
  1578.  
  1579.     fclose(*p_fp);        /* close old (pushed) file */
  1580.     *p_fp=fptmp;        /* set stackpointer to new first item */
  1581.  
  1582.     return(NULL);
  1583. }
  1584.  
  1585. static int popfile(struct item_file **pstack,FILE **p_fp)
  1586. {
  1587.     /* Get topmost Element from stack. Set 'pstack' to new topmost element.
  1588.      *
  1589.      * RC: NULL if all went fine, else
  1590.      *     ERROR if 'pstack' is empty.
  1591.      */
  1592.      
  1593.     struct item_file *itemtmp;
  1594.     FILE *fptmp;    
  1595.  
  1596.         /* Empty Stack is not allowed */
  1597.     if(!*pstack)
  1598.         return(NULL);
  1599.  
  1600.         /* Open old (previous pushed) File */
  1601.     if(!(fptmp=fopen( (*pstack)->filename,"r"))) /* Open New file */
  1602.     {    
  1603.         showerror(NULL,CANT_OPEN_FILE,(*pstack)->filename);
  1604.         return(ERROR);
  1605.     }
  1606.         /* Set Filepointer to old position */
  1607.     if(NULL!=fseek(fptmp,(*pstack)->filepos,SEEK_SET))
  1608.     {    
  1609.         showerror(NULL,CANT_SEEK_FILE,(*pstack)->filepos,(*pstack)->filename);
  1610.         fclose(fptmp);
  1611.         return(ERROR);
  1612.     }
  1613.  
  1614.     fclose(*p_fp);    /* Close old File */
  1615.  
  1616.     *p_fp=fptmp;    /* Copy new FilePointer */
  1617.  
  1618.     strcpy(actfilename, (*pstack)->filename);    /* get old filename */
  1619.     lnr = (*pstack)->lnr;                        /* get old linenumber */
  1620.     
  1621.     itemtmp   =(*pstack)->prev;        /* get pointer to next item */
  1622.     free(*pstack);                    /* free topmost element */
  1623.     *pstack=itemtmp;                /* set to new topmost element */
  1624.  
  1625.     return(NULL);
  1626. }
  1627.  
  1628. static int dodirective(struct listheader *plabel,struct objsize *pobj,char *ptok,int direc,int mode,int *orgflag)
  1629. {
  1630.     /*
  1631.      *    If mode==PARSE1
  1632.      *        increase 'pobj' about the needed space
  1633.      *    else if mode==PARSE2
  1634.      *        fill objbuffer
  1635.      *    '*orgflag' ist set to TRUE, if 'directive' is 'ORG'. This is done
  1636.      *  to determine in 'parseline()' if there is a skip in the object buffer.
  1637.      *  
  1638.      *    RC: NULL if all went fine, else
  1639.      *      ERROR 
  1640.      */
  1641.  
  1642. #define SLASH     1 
  1643. #define APOSTROPH 2
  1644.  
  1645.     u_short   adr,expr;
  1646.     char    *ntok;
  1647.     int        size=0,i,tmp,type;
  1648.     int        startsign=0,endsign=0;    /* determine DEFM String */
  1649.     u_char dummy;
  1650.     
  1651.     if(debugf)  puts("dodirective");
  1652.  
  1653.     *orgflag=FALSE;
  1654.     
  1655.     switch(direc)
  1656.     {
  1657.         case ORG :     ptok=strtok(NULL,"\n");    /* get Pointer to Adress */
  1658.                     ptok=skipspace(ptok);
  1659.                     if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1660.                     {
  1661.                         showerror(ptok,SYNTAX_ERROR);
  1662.                         return(ERROR);
  1663.                     }
  1664.                     if(doobjadr(pobj,(int)adr,OBJADABS))    /* set objectbuffer */
  1665.                         return(ERROR);
  1666.  
  1667.                         /* needed in parseline() to determine valid Object range */
  1668.                     *orgflag=TRUE;
  1669.  
  1670.                     if(mode==PARSE1)
  1671.                         return(NULL);
  1672.                     else if(mode==PARSE2)
  1673.                     {
  1674.                             /* check if Buffer is empty at new position */
  1675.                         if(dummy=*ACT_OBJ_ADDR(pobj))
  1676.                         {
  1677.                             showerror(ptok,DATA_OVERWRITE);
  1678.                             return(ERROR);
  1679.                         }
  1680.                         return(NULL);
  1681.                     }
  1682.                     break;
  1683.         case DEFS:    ptok=strtok(NULL,"\n");    /* get Pointer to Size */
  1684.                     ptok=skipspace(ptok);
  1685.                     if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1686.                     {
  1687.                         showerror(ptok,SYNTAX_ERROR);
  1688.                         return(ERROR);
  1689.                     }
  1690.                     size=adr;
  1691.                     if(mode==PARSE2)
  1692.                     {
  1693.                             /* check if Buffer is empty at new position */
  1694.                         for(i=0;i<size;i++)
  1695.                         {
  1696.                             if(dummy=*(ACT_OBJ_ADDR(pobj)+i))
  1697.                             {
  1698.                                 showerror(ptok,DATA_OVERWRITE);
  1699.                                 return(ERROR);
  1700.                             }
  1701.                         }
  1702.                         memset(ACT_OBJ_ADDR(pobj),FILL_CHAR,size);
  1703.                     }
  1704.                     return(doobjadr(pobj,size,OBJADREL));    /* increase objectbuffer */
  1705.                     break;
  1706.         case DEFW:    size=1;    /* Word == 2 Byte */
  1707.         case DEFB:    size++; /* Byte == 1 Byte */ 
  1708.                     i=0;
  1709.                     ntok=ptok+strlen(ptok);
  1710.                     while(ptok=strtok(NULL,","))    /* count more Bytes */
  1711.                     {
  1712.                         if(mode==PARSE2)
  1713.                         {
  1714.                             ptok=skipspace(ptok);
  1715.                             cutend(ptok); /* V1.24 hinzugefügt um mögliche Freiplätze nach einer 0-Zahl zuzulassen */
  1716.                             if(strtoint(plabel,ptok,&adr,mode))    /* substitude Adress */
  1717.                             {
  1718.                                 showerror(ptok,SYNTAX_ERROR);
  1719.                                 doobjadr(pobj,(i+1)*size,OBJADREL); /* successfull converted data still valid */
  1720.                                 return(ERROR);
  1721.                             }
  1722.                             if(dummy=*(ACT_OBJ_ADDR(pobj)+i))
  1723.                             {
  1724.                                 showerror(ptok,DATA_OVERWRITE);
  1725.                                 return(ERROR);
  1726.                             }
  1727.  
  1728.                             *(ACT_OBJ_ADDR(pobj)+i)=LOBYTE(adr);
  1729.  
  1730.                             if(size==2)
  1731.                             {
  1732.                                 if(dummy=*(ACT_OBJ_ADDR(pobj)+i+1))
  1733.                                 {
  1734.                                     showerror(ptok,DATA_OVERWRITE);
  1735.                                     return(ERROR);
  1736.                                 }
  1737.                                 *(ACT_OBJ_ADDR(pobj)+i+1)=HIBYTE(adr);
  1738.                             }
  1739.                         }
  1740.                         i+=size;
  1741.                     }
  1742.                     if(!i)
  1743.                     {
  1744.                         showerror(ntok,NO_EXPR_INSIDE);
  1745.                         return(ERROR);
  1746.                     }
  1747.                     return(doobjadr(pobj,i,OBJADREL));    /* increase objectbuffer */
  1748.                     break;
  1749.         case DEFM:  ptok += strlen(ptok)+1; /* set ptok,ntok behind directive DEFM */
  1750.  
  1751.                     ptok=skipspace(ptok);
  1752.                     switch(*ptok)
  1753.                     {
  1754.                         case '\'':    startsign=APOSTROPH;
  1755.                                     break;
  1756.                         case '/':    startsign=SLASH;
  1757.                                     break;
  1758.                         default:    showerror(ptok,NO_START_QUOTE);
  1759.                                     return(ERROR);
  1760.                                     break;
  1761.                     }
  1762.                     ntok=ptok+strlen(ptok)-1;    /* Pointer to end of string */
  1763.  
  1764.                         /* check last character of string */
  1765.                     switch(*ntok)
  1766.                     {
  1767.                         case '\'':    endsign=APOSTROPH;
  1768.                                     break;
  1769.                         case '/':    endsign=SLASH;
  1770.                                     break;
  1771.                         default:    showerror(ntok,NO_END_QUOTE);
  1772.                                     return(ERROR);
  1773.                                     break;
  1774.                     }
  1775.                         /* start and end quote are the same ? */
  1776.                     if(startsign^endsign)
  1777.                     {
  1778.                         showerror(ptok,QUOTES_DIFFER);
  1779.                         return(ERROR);
  1780.                     }
  1781.                         /* check if inside string no more quotes */
  1782. /*                    if(ntok!=strchr(ptok+1,*ptok))
  1783.                     {
  1784.                         showerror(ntok,"Multiple quotes");
  1785.                         return(ERROR);
  1786.                     }
  1787. */
  1788.  
  1789. /*                    if( (!(ptok = strchr(ptok,'\''))) || (!(ntok= strchr(ptok+1,'\''))))
  1790.                     {
  1791.                         if(!ptok)
  1792.                             ptok=ntok;
  1793.                         else
  1794.                             ptok=ptok+strlen(ptok);
  1795.                             
  1796.                         showerror(ptok,"Missing quote: \'");
  1797.                         return(ERROR);
  1798.                     }
  1799. */
  1800.                     if( (tmp = ntok-(++ptok)) < 1) 
  1801.                     {
  1802.                         showerror(ptok,NO_EXPR_INSIDE);
  1803.                         return(ERROR);
  1804.                     }
  1805.                     if(mode==PARSE2)
  1806.                     {
  1807.                         for(i=0;i<tmp;i++)
  1808.                         {
  1809.                             if(dummy=*(ACT_OBJ_ADDR(pobj)+i))
  1810.                             {
  1811.                                 showerror(ntok,DATA_OVERWRITE);
  1812.                                 return(ERROR);
  1813.                             }
  1814.                         }
  1815.                         strncpy(ACT_OBJ_ADDR(pobj),ptok,tmp);
  1816.                     }
  1817.                     return(doobjadr(pobj,tmp,OBJADREL));    /* increase objectbuffer */
  1818.                     break;
  1819.         case INCLUDE:
  1820.                     ptok=strtok(NULL,"\n");    /* get Pointer to Filename */
  1821.                     ptok=skipspace(ptok);
  1822.                     return(pushfile(&file_stack,ptok,&fpin));
  1823.                     break;
  1824.         case END:    endflag=TRUE;
  1825.                     return(NULL);
  1826.                     break;
  1827.         case LIST:        /* Switch LIST (verbose) ON or OFF */
  1828.                     ptok=strtok(NULL,"\n");    /* get switch LIST_ON or LIST_OFF */
  1829.                     ptok=skipspace(ptok);
  1830.                             /* search directive ON or OFF */
  1831.                     if(!ptok || ((type=finddirective(ptok))==ERROR) || (type!=LIST_OFF && type!=LIST_ON) )
  1832.                     {                                    
  1833.                         showerror(ptok,EXP_LIST_ON_OFF);
  1834.                         return(ERROR);
  1835.                     }
  1836.                         /* check if 'verbose' already set via Commandline Option */
  1837.                     if( (verbose&MODE_OPTION) || clockcycle )
  1838.                         return(NULL); /* Commandline Options has a greater Priority */
  1839.  
  1840.                     if(type==LIST_ON)
  1841.                         verbose=MODE_ALL;
  1842.                     else if(type==LIST_OFF)
  1843.                         verbose=NULL;
  1844.                     else 
  1845.                         INTERNAL_ERROR
  1846.                     return(NULL);
  1847.                     break;
  1848.         case COND:    ptok=strtok(NULL,"\n");    /* get expression */
  1849.                     ptok=skipspace(ptok);
  1850.                     if(strtoint(plabel,ptok,&expr,PARSE2))
  1851.                     {
  1852.                         if(ntok = strpbrk(ptok,"+-*/"))
  1853.                         {
  1854.                             showerror(ptok,CANT_RESOLVE);
  1855.                             return(ERROR);
  1856.                         }
  1857.                         else
  1858.                             expr = FALSE;
  1859.                     }
  1860.                     
  1861.                     assembleflag=(BOOL)expr; /* <>0 -> TRUE, Assemble */
  1862.                     return(NULL);
  1863.                     break;
  1864.         case ENDC:    assembleflag=TRUE;
  1865.                     return(NULL);
  1866.                     break;
  1867.         case EJECT:    if(verbose || clockcycle)
  1868.                         fputs("\f",stdout);
  1869.                     return(NULL);
  1870.                     break;
  1871.         case MACLIST:
  1872.         case HEADING:
  1873.         case MACRO:
  1874.         case ENDM:    showerror(ptok,NOT_IMPLEMENTED);
  1875.                     return(ERROR);
  1876.                     break;
  1877.     }
  1878.     INTERNAL_ERROR
  1879.     return(ERROR);
  1880. }
  1881.  
  1882. static int parseline(struct listheader *plabel,struct objsize *pobj,char *pwork,int mode)
  1883. /* List of all Label's */
  1884. /* Structure for start,end,actual position of objectbuffer */
  1885. /* Textline to parse */
  1886. /* PARSE1 or PARSE2 */                                           
  1887. {
  1888.     /*
  1889.      *    Parse a line for mnemomics or directives.
  1890.      *    Dependent if 'mode'==PARSE1 no objectcode is generated (only the size is counted)
  1891.      *              else if 'mode'==PARSE2 objectcode is generated.
  1892.      *
  1893.      *    - if comments exist, cut them.
  1894.      *     - if labels exists, note them in 'plabel' (PARSE1)
  1895.      *    - parse the command, check the correctness, determine the needed size,
  1896.      *      increment the objectbuffer and if 'mode'==PARSE2 generate the code
  1897.      *
  1898.      *    If any errors found in the string, they will be report by 'showerror()'
  1899.      *
  1900.      *    RC: NULL or
  1901.      *        ERROR if any serious ERRORS ocured
  1902.      *
  1903.      *        BTW: A wrong 'source line' isn't an error for this function.
  1904.      *             Syntax Error's will report by showerror() during the parsing.
  1905.      */
  1906.      
  1907. #    define POSOBJ 5        /* String Postition of 'Object Code' */
  1908. #    define POSCYCLE 5    /* String Postition of 'Clock Cycle' */
  1909. #    define POSSRCV 18    /* String Postition of 'Sourceline' (verbose) */
  1910. #    define POSSRCC 12    /* String Postition of 'Sourceline' (clockcycle) */
  1911.  
  1912.     char     *ptok,
  1913.             *tmp=NULL,
  1914.             clockbuf[BUFSIZ],
  1915.             verbbuf[BUFSIZ];
  1916.  
  1917.     int direc,nmne,orgflag;
  1918.  
  1919.     u_short value=0;
  1920.     u_short cycle=0;                /* if MNE found, MNE Clock Cycle */
  1921.     struct labelitem *pitem;
  1922.     BOOL  invalid=TRUE;            /* Flag to show if a Constant definition is invalid */
  1923.  
  1924.     int i,startpos;
  1925.     
  1926.     if(debugf)  puts("parseline");
  1927.  
  1928.         /* needed in 'verbose','intelhex' or 'clockcycle' mode */
  1929.     if(mode==PARSE2 && assembleflag)
  1930.     {
  1931.         startpos= pobj->actbyte;
  1932.  
  1933.         if(verbose) 
  1934.         {
  1935.             tmp=iwtoh((u_short)startpos,verbbuf);    /* Generate Objectaddress */
  1936.             strcpy(tmp,":              ");    /* Append ':' and clean Space */
  1937.             strcpy(&verbbuf[POSSRCV],pwork);    /* save line to print out in verbose mode */
  1938.         }
  1939.         if(clockcycle) 
  1940.         {
  1941.             tmp=iwtoh((u_short)lnr,clockbuf);    /* Generate Objectaddress */
  1942.             strcpy(tmp,":              ");    /* Append ':' and clean Space */
  1943.             strcpy(&clockbuf[POSSRCC],pwork);    /* save line to print out in clockcycle mode */
  1944.         }
  1945.     }
  1946.  
  1947.     killcomment(pwork);                /* remove all comments */
  1948.     cutend(pwork);
  1949.     if(!(ptok = strtok(pwork," \t")))        /* first token, No token there ? */
  1950.     {                                        /*  NO token, so finish */
  1951.         if(verbose&MODE_ALL)
  1952.             goto ENDPARSELINE;        /* print out Comment */
  1953.         if(clockcycle&MODE_ALL)
  1954.             goto ENDPARSELINE;        /* print out Comment */
  1955.         return(NULL);                /* nothing there to parse */
  1956.     }
  1957.  
  1958.     tmp = ptok + strlen(ptok) - 1;
  1959.  
  1960.     /*** is there a label ? ***/
  1961.     if(*tmp == ':') 
  1962.     {
  1963.         if( (mode==PARSE1) && assembleflag)
  1964.         {
  1965.             *tmp = '\0';                        /* cut ':' */
  1966.             if(dolabel(plabel,pobj,ptok))        /* manage label */
  1967.                 return(ERROR);
  1968.         }
  1969.         if(!(ptok = strtok(NULL," \t")))    /* next token */
  1970.             goto ENDPARSELINE;                /* nothing more there to parse */
  1971.     }
  1972.  
  1973.     /*** is there a directive ***/
  1974.     if( (direc=finddirective(ptok)) != ERROR)        /* search directives */
  1975.     {                                    
  1976.         if( (direc == EQU || direc == DEFL))    /* EQU/DEFL need at first a symbol name */
  1977.         {                                    /* they will be handled a few lines down */
  1978.             if(!assembleflag)
  1979.                 return(NULL);                  /* don't assemble -> ignore ERRORS */    
  1980.  
  1981.             showerror(ptok,NO_SYMBOL_NAME,ptok);
  1982.             return(NULL);
  1983.         }
  1984.         else
  1985.         {
  1986.             if(dodirective(plabel,pobj,ptok,direc,mode,&orgflag))
  1987.                 return(ERROR);
  1988.                 
  1989.                 /* all done this round ? */
  1990.             if( (!assembleflag) || (mode==PARSE1) || ( (!verbose) && (!intelhex) && (!clockcycle) ) )
  1991.                 return(NULL);
  1992.  
  1993.                 /* do 'verbose' or 'intelhex' stuff */
  1994.             nmne=pobj->actbyte-startpos;
  1995.  
  1996.             if(orgflag)
  1997.             {
  1998.                 startpos= pobj->actbyte;
  1999.                 nmne = 0;
  2000.             }
  2001.  
  2002.             if(intelhex&&nmne)
  2003.                 dointelhex(startpos,nmne,ACT_OBJ_ADDR(pobj)-nmne);
  2004.                 
  2005.                 /* less or equal 4 Bytes could be shown in actual line */
  2006.             if(verbose)
  2007.             {
  2008.                 if(nmne<=4)
  2009.                 {
  2010.                     tmp=&verbbuf[POSOBJ];
  2011.                     for(i=0;i<nmne;i++)
  2012.                     {
  2013.                         *tmp=' ';
  2014.                         tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2015.                     }
  2016.                     *tmp=' ';
  2017.                 }
  2018.                 else
  2019.                 {
  2020.                         /* more than 4 Bytes -> show in a new row */
  2021.                     puts(verbbuf);    /* show line with source Text, but without Bytes*/
  2022.                     tmp=&verbbuf[POSOBJ];
  2023.                     for(i=0;i<nmne&& (tmp<(&verbbuf[BUFSIZ]-3));i++)
  2024.                     {
  2025.                         *tmp=' ';
  2026.                         tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2027.                     }
  2028.                     *tmp='\0';
  2029.                 }
  2030.             }
  2031.                 /* check if there is something to print out */
  2032.             if(verbose || clockcycle)
  2033.                 goto ENDPARSELINE;
  2034.             else 
  2035.                 return(NULL);
  2036.         }
  2037.     }
  2038.  
  2039.     if(!assembleflag)
  2040.         return(NULL);    /* don't assemble -> do nothing */
  2041.  
  2042.     tmp = ptok; /* safe old start of begin parsing for second directive search */
  2043.  
  2044.     /*** Is there Z80 Mnemomic ? ***/
  2045.     if( !(domne(plabel,pobj,ptok,mode,&cycle)))    /* look for Mnemomics, parse them */
  2046.     {
  2047.         if(mode==PARSE2)
  2048.         {
  2049.             nmne = pobj->actbyte-startpos;
  2050.  
  2051.             if(intelhex&&nmne)
  2052.                 dointelhex(startpos,nmne,ACT_OBJ_ADDR(pobj)-nmne);
  2053.  
  2054.             if(verbose)
  2055.             {
  2056.                 tmp=&verbbuf[POSOBJ];
  2057.                 for(i=0;i<nmne;i++)
  2058.                 {
  2059.                     *tmp=' ';
  2060.                     tmp=ibtoh(*(ACT_OBJ_ADDR(pobj)+i-nmne),++tmp);
  2061.                 }
  2062.                 *tmp=' ';
  2063.             }
  2064.  
  2065.             if(clockcycle)
  2066.             {
  2067.                 if(cycle<0xff)    /* branch ? */
  2068.                 {   /* NO */
  2069.                     sprintf(&clockbuf[POSCYCLE]," %2d",cycle);
  2070.                     clockbuf[POSCYCLE+3]=' ';
  2071.                 }
  2072.                 else
  2073.                 {   /* Yes */
  2074.                     sprintf(&clockbuf[POSCYCLE]," %2d/%2d",(cycle&0xff00)>>8,cycle&0xff);
  2075.                     clockbuf[POSCYCLE+6]=' ';
  2076.                 }
  2077.             }
  2078.     
  2079.         }
  2080.         goto ENDPARSELINE;
  2081.     }
  2082.  
  2083.     /*** EQU/DEFL ***/
  2084.  
  2085.     strcpy(pwork,line+(tmp-pwork));            /* restore sourceline (cutted through 'domne()' */
  2086.     killcomment(pwork);
  2087.     cutend(pwork);
  2088.     ptok=strtok(pwork," \t");                /* first token (is also 'pwork') */
  2089.     if(!(ptok=strtok(NULL," \t")))            /* second token (assummed directive) */
  2090.     {
  2091.         showerror(ptok,UNKNOWN_COMMAND,pwork);
  2092.         return(NULL);
  2093.     }
  2094.  
  2095.     if( (direc=finddirective(ptok)) != ERROR)        /* search directives */
  2096.     {                                    
  2097.         if(direc != EQU && direc != DEFL)        /* 'direc' must be EQU or DEFL */
  2098.         {
  2099.             showerror(ptok,UNKNOWN_COMMAND);
  2100.             return(NULL);
  2101.         }
  2102.         if(!(ptok=strtok(NULL,"\n")))            /* third token (constant assummed) */
  2103.         {
  2104.             showerror(pwork,EXPECT_CONSTANT);
  2105.             return(NULL);
  2106.         }
  2107.         ptok=skipspace(ptok);
  2108.  
  2109.         invalid = strtoint(plabel,ptok,&value,mode);
  2110.  
  2111.         if(mode==PARSE2)
  2112.         {
  2113.             if(invalid)        /* convert to int */
  2114.             {
  2115.                 /* Just to report a more detailed error message */
  2116.                 strtok(ptok," \t");    /* clear everything behind token */
  2117.                 if(getlabel(plabel,ptok))    /* check if Symbol name exists */
  2118.                     showerror(ptok,CANT_RESOLVE);
  2119.                 else
  2120.                     showerror(ptok,SYNTAX_ERROR);
  2121.                 return(NULL);
  2122.             }
  2123.         }
  2124.  
  2125.         if(pitem=getlabel(plabel,pwork))    /* check if Symbol name exists */
  2126.         {
  2127.             if( direc!=DEFL || pitem->type != L_DEFL )    /* directive type = EQU ? */
  2128.             {
  2129.                 if( direc != pitem->type )
  2130.                 { 
  2131.                     showerror(pwork,LABEL_DECL_EQUDEFL);    /* EQU definition can't */
  2132.                     return(NULL);                                /*  redefined */
  2133.                 }
  2134.                 if(mode==PARSE1)    /* first parse -> error */
  2135.                 {
  2136.                     showerror(pwork,LABEL_DECL_TWICE);    /* EQU definition can't */
  2137.                     return(NULL);                                /*  redefined */
  2138.                 }
  2139.             }
  2140.             if(pitem->valid = !invalid)
  2141.                 pitem->value = value;        /* -> direc == DEFL. take new value */
  2142.             goto ENDPARSELINE;
  2143.         }
  2144.         else                                /* Symbol name is new */
  2145.         {
  2146.             if(mode==PARSE2)
  2147.             {
  2148.                     /* this should never be happen */
  2149.                 INTERNAL_ERROR
  2150.                 return(ERROR);                        
  2151.             }
  2152.             if(SERIOUS==(int)insertlabel(plabel,pwork,direc,value,!invalid)) /* insert constant definition */
  2153.             {
  2154.                 showerror(pwork,NO_MEMORY);
  2155.                 return(ERROR);                        
  2156.             }
  2157.             goto ENDPARSELINE;
  2158.         }
  2159.     }
  2160.     else
  2161.     {
  2162.         showerror(ptok,UNKNOWN_COMMAND);
  2163.         return(NULL);
  2164.     }
  2165.  
  2166. ENDPARSELINE:
  2167.     if(!assembleflag)
  2168.         return(NULL);
  2169.  
  2170.     if( (mode==PARSE2) && verbose)
  2171.         puts(verbbuf);
  2172.     if( (mode==PARSE2) && clockcycle)
  2173.         puts(clockbuf);
  2174.     return(NULL);
  2175. }
  2176.  
  2177.  
  2178. static int readsrc(struct listheader *plabel,struct objsize *pobj,char *p_actfilename)
  2179. {
  2180.     /*
  2181.      *    Parse File 'fp' two times.
  2182.      *    First parse: - Count Object code size
  2183.      *                 - Fill list 'plabel' with label name and either a memory
  2184.      *                   position or a constant definition
  2185.      *    Second parse: - Allocate Object code Buffer
  2186.      *                  - fill the buffer with appropriate Object code
  2187.      *                  - use 'label' to reference all symbols
  2188.      *
  2189.      *    RC: number of object bytes if every went fine,else
  2190.      *        NULL and print an error message 
  2191.      */
  2192.     
  2193.     char *pos;    
  2194.     u_char *tmp;
  2195.     int length;
  2196.     BOOL flag=TRUE;
  2197.  
  2198.     if(debugf)  puts("readsrc");
  2199.  
  2200.     if(!(fpin=fopen(p_actfilename,"r"))) /* Open New file */
  2201.     {    
  2202.         fprintf(stderr,CANT_OPEN_FILE,p_actfilename);
  2203.         return(NULL);
  2204.     }
  2205.  
  2206.     /******************** Parse 1 ********************/
  2207.     fputs("Parse 1\n",stderr);
  2208.  
  2209.     while(flag)                    /* parse source file */
  2210.     {
  2211.         if(feof(fpin))            /* no more Data ? */ 
  2212.         {
  2213.             if(file_stack)            /* Are there still any source files ? */
  2214.             {
  2215.                 if(popfile(&file_stack,&fpin))
  2216.                     return(NULL);    /* Error */
  2217.             }
  2218.             else
  2219.                 flag=FALSE;                /* No, so quit while() */
  2220.  
  2221.             continue;                /* go to while() */
  2222.         }
  2223.  
  2224.         if(pos=fgets(line,BUFSIZ,fpin))    /* get next line */
  2225.         {
  2226.             strcpy(work,line);            /* 'work' is work buffer */
  2227.             lnr++;                        /* line number counting */
  2228.             if(parseline(plabel,pobj,work,PARSE1))    /* parse the line */
  2229.                 return(NULL);            /* something terrible must be happen */
  2230.  
  2231.             if(endflag)
  2232.             {
  2233.                 endflag=flag=FALSE;
  2234.                 while(file_stack)            /* Are there still any source files ? */
  2235.                 {
  2236.                     if(popfile(&file_stack,&fpin))
  2237.                         return(NULL);    /* Error */
  2238.                 }
  2239.             }
  2240.         }
  2241.     }
  2242.  
  2243.     if(errors)
  2244.         return(NULL);
  2245.         
  2246.     length=pobj->lastbyte - pobj->firstbyte;
  2247.  
  2248.     if(length)
  2249.     {    /* Just allocate Buffer, if it is really needed */
  2250.          if(!(tmp=pobj->objbuffer=(u_char *)calloc(sizeof(unsigned char),length)))
  2251.         {
  2252.             fputs("Error: Can't allocate memory for Objectbuffer\n",stderr);
  2253.             return(NULL);
  2254.         }
  2255.     }
  2256.     pobj->actbyte = pobj->firstbyte; /* Set counter to start */
  2257.  
  2258.     /******************** Parse 2 ********************/
  2259.     fputs("Parse 2\n",stderr);
  2260.     rewind(fpin);
  2261.     lnr=0;
  2262.     if(clockcycle)
  2263.         puts("Line: Cycle Source");
  2264.  
  2265.     flag=TRUE;
  2266.     while(flag)                    /* parse source file */
  2267.     {
  2268.         if(feof(fpin))            /* no more Data ? */ 
  2269.         {
  2270.             if(file_stack)            /* Are there still any source files ? */
  2271.             {
  2272.                 if(popfile(&file_stack,&fpin))
  2273.                     return(NULL);    /* Error */
  2274.             }
  2275.             else
  2276.                 flag=FALSE;                /* No, so quit while() */
  2277.  
  2278.             continue;                /* go to while() */
  2279.         }
  2280.  
  2281.         if(pos=fgets(line,BUFSIZ,fpin))    /* get next line */
  2282.         {
  2283.             strcpy(work,line);            /* 'work' is work buffer */
  2284.             lnr++;                        /* line number counting */
  2285.             cutend(work);
  2286.             if(parseline(plabel,pobj,work,PARSE2))    /* parse the line */
  2287.                 return(NULL);            /* something terrible must be happen */
  2288.  
  2289.             if(endflag)
  2290.             {
  2291.                 flag=FALSE;
  2292.                 while(file_stack)            /* Are there still any source files ? */
  2293.                 {
  2294.                     if(popfile(&file_stack,&fpin))
  2295.                         return(NULL);    /* Error */
  2296.                 }
  2297.             }
  2298.         }
  2299.     }
  2300.     if(intelhex)
  2301.         dointelhex(ERROR,0,NULL);
  2302.  
  2303.     if(debugv) fprintf(stderr,"generated Object Bytes:%d\n",length);    
  2304.  
  2305.     return(length);
  2306. }
  2307.  
  2308.  
  2309. static void cleanup(void)
  2310. {
  2311.     struct item_file *p_fs;
  2312.  
  2313.     if(ih_head.list)    
  2314.         free(ih_head.list);
  2315.  
  2316.     if(label.list)      
  2317.         free(label.list);
  2318.  
  2319.     if(object.objbuffer)    
  2320.         free(object.objbuffer);
  2321.  
  2322.     if(file_stack)
  2323.     {
  2324.         do {
  2325.             p_fs = file_stack->prev;
  2326.             free(file_stack);
  2327.             file_stack = p_fs;
  2328.         } while(p_fs);
  2329.     }
  2330.  
  2331.     if(fpin)              fclose(fpin);    
  2332.     if(fpout)              fclose(fpout);    
  2333.  
  2334.     return;
  2335. }
  2336.  
  2337. static void handlesig(int sig)
  2338. {
  2339.     fflush(stdout);
  2340.     puts("caz broken");
  2341.     cleanup();
  2342.     exit(RETURN_WARN);
  2343. }
  2344.  
  2345. int main(int argc,char *argv[])
  2346. {
  2347.     char    *outfile="a.out",*intelhexfile=NULL,*labelfile=NULL;
  2348.     int        length;
  2349.  
  2350.  
  2351.     signal(SIGINT,handlesig);
  2352.  
  2353.     actfilename[0] = '\0';
  2354.  
  2355.     if(debugf)  puts("main");
  2356.  
  2357.     if(argc==1)         /* check commandline arguments */
  2358.         goto USAGE;
  2359.  
  2360.     if((argc==2) && (*argv[1]=='?') )
  2361.         goto USAGE;
  2362.     
  2363.     while(--argc)
  2364.     {
  2365.         if( (**(++argv)) == '-')
  2366.         {
  2367.             switch(*((*argv)+1))
  2368.             {
  2369.                 case 'd':    debugv=TRUE;            /* Flag */
  2370.                             break;
  2371.                 case 'D':    debugf=TRUE;            /* Flag */
  2372.                             break;
  2373.                 case 'v':    verbose = MODE_OPTION+MODE_MNE;
  2374.                             break;
  2375.                 case 'V':    verbose = MODE_OPTION+MODE_ALL;        /* Flag */
  2376.                             break;
  2377.                 case 'c':    clockcycle = MODE_MNE;
  2378.                             break;
  2379.                 case 'C':    clockcycle = MODE_ALL;        /* Flag */
  2380.                             break;
  2381.                 case 's':
  2382.                 case 'S':    showsymbols=TRUE;        /* Flag */
  2383.                             break;
  2384.                 case 'o':
  2385.                 case 'O':     if(!(--argc))
  2386.                               {
  2387.                                   fprintf(stderr,"Missing filename behind '-o'\n");
  2388.                                   goto USAGE;
  2389.                               }
  2390.                               outfile = *++argv;
  2391.                               break;
  2392.                 case 'w':
  2393.                 case 'W':     if(!(--argc))
  2394.                               {
  2395.                                   fprintf(stderr,"Missing filename behind '-w'\n");
  2396.                                   goto USAGE;
  2397.                               }
  2398.                               labelfile = *++argv;
  2399.                               break;
  2400.                 case 'i':
  2401.                 case 'I':     if(!(--argc))
  2402.                               {
  2403.                                   fprintf(stderr,"Missing filename behind '-e'\n");
  2404.                                   goto USAGE;
  2405.                               }
  2406.                               intelhexfile = *++argv;
  2407.                             intelhex=TRUE;            /* Flag */
  2408.                               break;
  2409.                 case 'h':
  2410.                 case 'H':
  2411.                 case '?':    goto USAGE1;
  2412.                             break;
  2413.                 default:    fprintf(stderr,"Unknown commandline option\n");
  2414.                               goto USAGE;
  2415.             }
  2416.         }
  2417.         else
  2418.         {    
  2419.             if(actfilename[0])
  2420.                 goto USAGE;
  2421.             strcpy(actfilename,*argv);
  2422.         }
  2423.     }
  2424.     
  2425.     fputs(vers,stderr);
  2426.     fputs(COPYRIGHT,stderr);
  2427.  
  2428.         /* Check if CLOCK & VERBOSE Mode is active */
  2429.     if(clockcycle && verbose)
  2430.     {
  2431.         fputs(CLOCK_OR_VERBOSE,stderr);
  2432.         goto LEAVEALL;
  2433.     }
  2434.  
  2435.     if(init(&label,&object))    /* initialize lists/buffers */
  2436.         exit(RETURN_ERROR);
  2437.     
  2438.     length=readsrc(&label,&object,actfilename);
  2439.  
  2440.     if(errors)
  2441.         fprintf(stderr,"\n\nAssembling failed.\nFound %d errors.\n",errors);
  2442.  
  2443.     if(showsymbols) 
  2444.         symboltable(&label);                        
  2445.  
  2446.     if(labelfile) 
  2447.         writesymboltable(&label,labelfile);                        
  2448.  
  2449.  
  2450.         /* if readsrc() don't generate any Objectcode, quit assembler */
  2451.     if(!length)
  2452.         goto LEAVEALL;
  2453.  
  2454.     if(!(fpout = fopen(outfile,"wb")))    /* open file where to write object code */
  2455.     {
  2456.         perror("Can't open file:");
  2457.         exit(RETURN_WARN);
  2458.     }
  2459.     if(length!=fwrite(object.objbuffer,1,length,fpout))
  2460.     {
  2461.         perror("Writing Objectfile failed");
  2462.         goto LEAVEALL;
  2463.     }
  2464.     fclose(fpout);
  2465.     fpout=NULL;
  2466.  
  2467.     if(intelhex)
  2468.     {
  2469.         if(!(fpout = fopen(intelhexfile,"wb")))    /* open file where to write INTELHEX Code */
  2470.         {
  2471.             sprintf(errortext,"Can't open file output File '%s'\n",actfilename);
  2472.             perror(errortext);
  2473.             exit(RETURN_WARN);
  2474.         }
  2475.         length=ih_head.actitem;
  2476.         if(length!=fwrite(ih_head.list,1,length,fpout))
  2477.         {
  2478.             perror("Writing INTELHEX File failed");
  2479.             goto LEAVEALL;
  2480.         }
  2481.     }
  2482.  
  2483.     goto LEAVEALL;                /* exit */
  2484.  
  2485. USAGE:
  2486.     fprintf(stderr,"USAGE: 'caz OPTIONS [assembler filename]'\n");
  2487. USAGE1:    
  2488.     fprintf(stderr,
  2489.            "%s"
  2490.            COPYRIGHT
  2491.            "\nOPTIONS are:\n\n"
  2492.            "-o [Output Filename]   File where to write the generated Objectcode.\n"
  2493.            "-d Debug Mode          Just for development of 'caz' (d=Value,D=Function).\n"
  2494.            "-v/V Verbose Mode      Print on 'stdout' generated Objectcode with\n"
  2495.            "                        with Adresses,Mnemomic,Source (v=MNE,V=ALL).\n"
  2496.            "-c/C Clock Cycle       Print on 'stdout' Clock Cycles for every Mnemomic\n"
  2497.            "-w [Filename]          Write out symbol definitions (Z80 Assembler Format).\n"
  2498.            "-s Print Symbol Table  Print out symbol definitions (more detailed). \n"
  2499.            "-i [IntelHex Filename] Generate a complete Object File in 'IntelHex'\n"
  2500.            "                        Format (used by many Eprommer).\n",&vers[7]);
  2501.     return(1);
  2502.  
  2503. LEAVEALL:
  2504.     cleanup();
  2505.     exit(RETURN_OK);
  2506. }
  2507.